function [cfg] = ft_definetrial(cfg)

% FT_DEFINETRIAL defines the segments of data that will be used for
% further processing and analysis, i.e. the pieces of data that will
% be read in by FT_PREPROCESSING. Trials are defined by their begin
% and end sample in the data file and each trial has an offset that
% defines where the relative t=0 point (usually the sample at which
% the trigger is detected) is for that trial.
%
% Use as
%   [cfg] = ft_definetrial(cfg)
% where the configuration structure should contain
%   cfg.trialdef   = structure with details of trial definition, see below
%   cfg.trialfun   = string with function name, see below (default = 'ft_trialfun_general')
% and furthermore
%   cfg.dataset     = string with the filename
% or
%   cfg.headerfile  = string with the filename
%   cfg.datafile    = string with the filename
% and optionally
%   cfg.headerformat
%   cfg.dataformat
%
% A call to FT_DEFINETRIAL results in the trial definition "trl" being
% added to the output configuration structure. The trials are defined
% according to the triggers, trials or other events in the data, or
% from a user-specified MATLAB function (subsequently referred to as
% the trial function) which returns "trl". The user can specify the
% name of his/her custom trial function that is tailored to the
% experimental paradigm, or use the default trial function
% FT_TRIALFUN_GENERAL.
%
% The trial definition "trl" is an Nx3 matrix, N is the number of trials.
% The first column contains the sample-indices of the begin of each trial
% relative to the begin of the raw data, the second column contains the
% sample-indices of the end of each trial, and the third column contains
% the offset of the trigger with respect to the trial. An offset of 0
% means that the first sample of the trial corresponds to the trigger. A
% positive offset indicates that the first sample is later than the trigger,
% a negative offset indicates that the trial begins before the trigger.
%
% The trial definition "trl" can contain additional columns besides the
% required three that represent begin, end and offset. These additional
% columns can be used by a custom trialfun to provide numeric information
% about each trial such as trigger codes, response latencies, trial
% type and response correctness. The additional columns of the "trl"
% matrix will be represented in data.trialinfo after FT_PREPROCESSING.
%
% If FT_TRIALFUN_GENERAL has been used to generate the "trl" matrix, the
% function may return a fourth column in the trl-matrix, that refers to
% the event-code for the corresponding trial. It depends on the acquisition
% system whether or not this fourth column is returned. In general, this
% fourth column is generated by default if the event codes are represented
% numerically, or as a string starting with 'S' or 'R' (for BrainVision data)
%
% Simple trial definitions (e.g. based on a single trigger) are supported
% by FT_TRIALFUN_GENERAL, which is the default trial function. This function
% supports the following options
%   cfg.trialdef.eventtype  = 'string'
%   cfg.trialdef.eventvalue = number, string or list with numbers or strings
%   cfg.trialdef.prestim    = number, latency in seconds (optional)
%   cfg.trialdef.poststim   = number, latency in seconds (optional)
%
% If you specify cfg.trialdef.eventtype  = '?' a list with the events in your
% data file will be displayed on screen.
%
% If you want to read all data from a continuous file in a single or in
% multiple segments, TRIALFUN_GENERAL understands the following options
%    cfg.trialdef.triallength = duration in seconds (can also be 1 or Inf)
%    cfg.trialdef.ntrials     = number of trials (can also be 1 or Inf)
%
% If you need to define the segments of interest on the basis of a conditional
% sequence of events (e.g. stimulus trigger followed by a correct response),
% you should supply your own trial function and specify that as cfg.trialfun.
% See below for pointers to some examples.
%
% Both the default trial function and your own supplied custom trial
% functions in general will call FT_READ_EVENT to collect all event
% information (such as triggers) from your dataset and to select
% pieces of data according to this information.
%
% The cfg.trialfun option is a string containing the name of a function
% that you wrote yourself and that FT_DEFINETRIAL will call. The
% function should take the cfg-structure as input and should give a
% NxM matrix with M equal to or larger than 3) in the same format as
% "trl" as the output. You can add extra custom fields to the
% configuration structure to pass as arguments to your own trialfun.
% Furthermore, inside the trialfun you can use the FT_READ_EVENT
% function to get the event information from your data file.
%
% See also FT_PREPROCESSING, FT_READ_HEADER, FT_READ_DATA, FT_READ_EVENT,
% FT_TRIALFUN_GENERAL, FT_TRIALFUN_EXAMPLE1, FT_TRIALFUN_EXAMPLE2

% Undocumented local options:
% cfg.datafile
% cfg.dataset
% cfg.event
% cfg.trl
% cfg.version

% Copyright (C) 2003, Robert Oostenveld, FCDC
%
% This file is part of FieldTrip, see http://www.fieldtriptoolbox.org
% for the documentation and details.
%
%    FieldTrip is free software: you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation, either version 3 of the License, or
%    (at your option) any later version.
%
%    FieldTrip is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.
%
%    You should have received a copy of the GNU General Public License
%    along with FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id$

% these are used by the ft_preamble/ft_postamble function and scripts
ft_revision = '$Id$';
ft_nargin   = nargin;
ft_nargout  = nargout;

% do the general setup of the function
ft_defaults
ft_preamble init
ft_preamble loadvar
ft_preamble provenance

% the ft_abort variable is set to true or false in ft_preamble_init
if ft_abort
  return
end

% check if the input cfg is valid for this function
cfg = ft_checkconfig(cfg, 'dataset2files', 'yes');

if ~isfield(cfg, 'trl') && (~isfield(cfg, 'trialfun') || isempty(cfg.trialfun))
  % there used to be other system specific trialfuns in previous versions
  % of FieldTrip, but they are deprecated and not included in recent
  % versions any more
  cfg.trialfun = 'ft_trialfun_general';
  ft_warning('no trialfun was specified, using ft_trialfun_general');
end

% create the trial definition for this dataset and condition
if isfield(cfg, 'trl')
  % the trial definition is already part of the configuration
  ft_info('retaining existing trial definition\n');
  trl = cfg.trl;
  if isfield(cfg, 'event')
    ft_info('retaining existing event information\n');
    event = cfg.event;
  else
    event = [];
  end

elseif isfield(cfg, 'trialfun')

  trialfunSpecified = cfg.trialfun;
  cfg.trialfun = ft_getuserfun(cfg.trialfun, 'trialfun');

  if isempty(cfg.trialfun)
    ft_error('the specified trialfun ''%s'' was not found', trialfunSpecified);
  else
    ft_info('evaluating trialfunction ''%s''\n', func2str(cfg.trialfun));
  end

  % determine the number of outpout arguments of the user-supplied trial function
  try
    % the nargout function in MATLAB 6.5 and older does not work on function handles
    num = nargout(cfg.trialfun);
  catch
    num = 1;
  end
  if num==1
    % the user-defined function only gives back the trial definition
    trl   = feval(cfg.trialfun, cfg);
    event = [];
  else
    % the user-defined function also gives back detailed information about
    % conditions, reaction time or any other information
    [trl, event] = feval(cfg.trialfun, cfg);
  end
else
  ft_error('no trialfunction specified, see FT_DEFINETRIAL for help');
end

if isfield(cfg, 'trialdef') && isfield(cfg.trialdef, 'eventtype') && isequal(cfg.trialdef.eventtype, '?')
  % give a gentle message instead of an error
  ft_info('no trials have been defined yet, see FT_DEFINETRIAL for further help\n');
elseif size(trl,1)<1
  ft_error('no trials were defined, see FT_DEFINETRIAL for help');
end

% add the new trials and events to the output configuration
ft_info('found %d events\n', length(event));
cfg.event = event;
ft_info('created %d trials\n', size(trl,1));
cfg.trl = trl;

% do the general cleanup and bookkeeping at the end of the function
ft_postamble provenance
ft_postamble savevar
